/**
 * 生成一个随机数字符串
 * @returns {string} 返回一个0到1亿之间的随机数，并转换为字符串
 */
function randomNumber() {
  return (Math.random() * 1e8).toFixed('0')
}

/**
 * 表格样式常量定义
 * 包含基础样式、列表表格样式和嵌套表格样式
 */
const STYLES = {
  // 基础边框和内边距
  BORDER: '1px solid #ddd',
  PADDING: '4px',

  // 基础表格样式
  BASE_TABLE: {
    borderCollapse: 'collapse',
    borderSpacing: '0'
  },

  // 列表表格特殊样式 - 去除首尾行边框
  LIST_TABLE: `
    .list-table tr:first-child td,
    .list-table thead tr:first-child th {
      border-top: none !important;
    }
    .list-table tr:last-child td {
      border-bottom: none !important;
    }
  `,

  // 嵌套表格特殊样式 - 去除所有边框
  NESTED_TABLE: `
    .nested-table tr:first-child td {
      border-top: none !important;
    }
    .nested-table tr:last-child td {
      border-bottom: none !important;
    }
    .nested-table tr td:first-child {
      border-left: none !important;
    }
    .nested-table tr td:last-child {
      border-right: none !important;
    }
    .nested-table tr td[colspan] {
      width: auto !important;
    }
  `
}

/**
 * 应用基础样式到DOM元素
 * @param {HTMLElement} element - 要应用样式的DOM元素
 * @param {Object} [customStyles={}] - 自定义样式对象，会覆盖基础样式
 * @param {string} [baseClass=''] - 基础CSS类名
 * @description
 * 应用基础边框和内边距样式，并合并自定义样式。
 * 如果提供了baseClass，会添加到元素的classList中。
 */
function applyCommonStyles(element, customStyles = {}, baseClass = '') {
  // 应用基础样式
  const baseStyles = {
    border: STYLES.BORDER,
    padding: STYLES.PADDING
  }

  // 合并基础样式和自定义样式
  Object.assign(element.style, baseStyles, customStyles)

  // 添加基础类名
  if (baseClass) {
    element.classList.add(baseClass)
  }
}

/**
 * 获取带单位的宽度值
 * @param {number|string} width - 宽度值，可以是数字或字符串
 * @param {string} [defaultUnit='%'] - 默认单位，当宽度值不带单位时使用
 * @returns {string} 带单位的宽度字符串
 * @description
 * 将宽度值转换为带单位的字符串，处理以下情况：
 * 1. 空值返回空字符串
 * 2. 数字类型添加默认单位
 * 3. 字符串类型检查是否已有单位，没有则添加默认单位
 * 4. 支持常见单位：px, %, em, rem, vw, vh
 */
function getWidthWithUnit(width, defaultUnit = '%') {
  if (!width) return ''

  // 处理数字类型
  if (typeof width === 'number') {
    return `${width}${defaultUnit}`
  }

  // 处理字符串类型
  if (typeof width === 'string') {
    const trimmed = width.trim()
    // 检查是否已有有效单位
    if (/px|%|em|rem|vw|vh$/.test(trimmed)) {
      return trimmed
    }
    // 无单位则添加默认单位
    return `${trimmed}${defaultUnit}`
  }

  // 其他类型返回默认单位
  return `${width}${defaultUnit}`
}

/**
 * 创建带样式的DOM元素
 * @param {string} tag - 元素标签名
 * @param {Object} [styles={}] - 样式对象
 * @param {string} [className=''] - CSS类名
 * @returns {HTMLElement} 创建的DOM元素
 */
function createStyledElement(tag, styles = {}, className = '') {
  const element = document.createElement(tag)
  Object.assign(element.style, styles)
  if (className) element.className = className
  return element
}

/**
 * 添加样式到文档
 * @param {string} styleContent - CSS样式内容
 * @param {string} className - 关联的类名
 */
function addStyleToDocument(styleContent, className) {
  const style = document.createElement('style')
  style.textContent = styleContent
  try {
    document.head.appendChild(style)
  } catch (e) {
    console.error('Failed to add style:', e)
  }
}

/**
 * 创建表格单元格元素
 * @param {string|Object} content - 单元格内容，可以是文本或对象
 * @param {Object} [config={}] - 单元格配置
 * @param {number} [config.colspan=1] - 列跨度
 * @param {number} [config.rowspan=1] - 行跨度
 * @param {Object} [styles={}] - 基础样式对象
 * @returns {HTMLTableCellElement} 创建的单元格元素
 * @description
 * 创建表格单元格(td)，支持以下功能：
 * 1. 文本内容或复杂对象内容
 * 2. 特殊模式处理(img/link)
 * 3. 列/行跨度配置
 * 4. 样式合并
 */
function createTableCell(content, cellSource = {}, styles = {}) {
  const cell = document.createElement('td')
  applyCommonStyles(cell, styles)

  /**
   * 处理特殊模式内容(img/link)
   * @param {Object} contentObj - 内容对象
   * @param {HTMLElement} parent - 父元素
   */
  const handleModeContent = (contentObj, parent) => {
    parent.innerHTML = ''

    switch (contentObj.mode) {
      case 'img':
        if (contentObj.modeUrl) {
          const img = document.createElement('img')
          img.src = contentObj.modeUrl
          img.alt = img.title = contentObj.text || ''
          if (contentObj.modeStyle) {
            Object.assign(img.style, contentObj.modeStyle)
          }
          parent.appendChild(img)
        }
        break

      case 'link':
        if (contentObj.modeUrl) {
          const a = document.createElement('a')
          a.href = contentObj.modeUrl
          a.target = '_blank'
          a.textContent = contentObj.text || ''
          Object.assign(a.style, {
            color: 'blue',
            // textDecoration: 'underline',
            borderBottom: '1px solid blue'
          })
          if (contentObj.modeStyle) {
            Object.assign(a.style, contentObj.modeStyle)
          }
          parent.appendChild(a)
        }
        break

      case 'radio':
      case 'checkbox':
        if (contentObj.modeOptions) {
          const _ary = document.createDocumentFragment()

          const raidoName =
            contentObj.modeRadioName || contentObj.modeCheckboxName || `radio_${randomNumber()}`

          contentObj.modeOptions.forEach(({ label, value, labelStyle, valueStyle }) => {
            const radio = document.createElement('input')
            radio.type = contentObj.mode || 'radio'
            radio.value = value
            radio.name = raidoName
            radio.id = `rdo_${randomNumber()}`
            Object.assign(
              radio.style,
              contentObj.modeStyle,
              { cursor: 'pointer', verticalAlign: 'middle' },
              valueStyle
            )
            if (contentObj.mode == 'radio' && contentObj.modeValue == value) {
              radio.setAttribute('checked', true)
            } else if (contentObj.mode == 'checkbox' && contentObj.modeValue.includes(value)) {
              radio.setAttribute('checked', true)
            }

            const lbl = document.createElement('label')
            lbl.textContent = label
            lbl.setAttribute('for', radio.id)
            Object.assign(
              lbl.style,
              contentObj.modeStyle,
              { cursor: 'pointer', verticalAlign: 'middle' },
              labelStyle
            )

            _ary.appendChild(radio)
            _ary.appendChild(lbl)
          })
          parent.appendChild(_ary)
        }

        break

      default:
        parent.textContent = contentObj.text || ''
    }
  }

  // 处理内容
  if (typeof content === 'object' && content !== null) {
    // 处理模式内容
    if (content.mode) {
      handleModeContent(content, cell)
    } else {
      cell.textContent = content.text || ''
      if (content.textHtml) {
        cell.innerHTML = content.textHtml
      }
    }

    // 合并内容样式
    if (content.style) {
      Object.assign(cell.style, content.style)
    }
  } else if (typeof content === 'string') {
    // 简单文本内容
    cell.textContent = content
  } else if (content instanceof HTMLElement) {
    // 已经处理好的HTML元素
    cell.appendChild(content)
  }

  if (typeof cellSource === 'object') {
    const { colspan = 1, rowspan = 1 } = cellSource.config || {}
    if (colspan > 1) cell.colSpan = colspan
    if (rowspan > 1) cell.rowSpan = rowspan
  }

  return cell
}

/**
 * 生成列表格式的表格
 * @param {Object} node - 表格配置对象
 * @param {Array} node.columns - 列配置数组
 * @param {Array} node.list - 表格数据数组
 * @returns {HTMLTableElement} 生成的表格元素
 * @description
 * 1. 处理表头配置，支持自定义列宽
 * 2. 处理表体数据，保持与表头对应
 * 3. 添加特殊样式处理首尾行边框
 * @example
 * generateListTable({
 *   columns: [
 *     {label: '姓名', width: 30},
 *     {label: '年龄', width: 20}
 *   ],
 *   list: [
 *     ['张三', '25'],
 *     ['李四', '30']
 *   ]
 * })
 */
function generateListTable(node) {
  const { columns = [], list = [] } = node.data || {}
  const table = createStyledElement(
    'table',
    {
      width: '100%',
      ...STYLES.BASE_TABLE
    },
    'list-table'
  )

  addStyleToDocument(STYLES.LIST_TABLE, 'list-table')

  // 渲染表头
  if (columns.length > 0) {
    const thead = document.createElement('thead')
    const headerRow = document.createElement('tr')

    // 添加colgroup定义列宽
    const colgroup = document.createElement('colgroup')
    columns.forEach((col) => {
      const colElement = document.createElement('col')
      if (col.width) {
        colElement.style.width = getWidthWithUnit(col.width)
      }
      colgroup.appendChild(colElement)
    })
    table.appendChild(colgroup)

    columns.forEach((col, index) => {
      const styles = { fontWeight: 'normal', textAlign: 'left' }
      if (index === 0) styles.borderLeft = '0'
      if (index === columns.length - 1) styles.borderRight = '0'

      // 解析align属性
      if (col.align) {
        const [headerAlign] = col.align.split('|')
        if (headerAlign) {
          styles.textAlign = headerAlign.trim()
        }
      }

      const th = document.createElement('th')
      applyCommonStyles(th, styles)
      th.textContent = col.label || ''
      if (col.labelHtml) {
        th.innerHTML = col.labelHtml
      }
      if (col.style) Object.assign(th.style, col.style)
      headerRow.appendChild(th)
    })

    thead.appendChild(headerRow)
    table.appendChild(thead)
  }

  // 渲染数据行
  if (list.length > 0 && columns.length > 0) {
    const tbody = document.createElement('tbody')

    list.forEach((row, rowIndex) => {
      // 跳过无效行
      if (!Array.isArray(row)) return

      const tr = document.createElement('tr')

      let jumpCols = 0
      // 确保处理所有列，即使数据不全
      for (let cellIndex = 0; cellIndex < columns.length; cellIndex++) {
        const cell = row[cellIndex] !== undefined ? row[cellIndex] : ''
        const styles = {}

        if (jumpCols > 0) {
          jumpCols--
          continue
        }

        // 列对齐样式
        if (columns[cellIndex]?.align) {
          const [, bodyAlign] = columns[cellIndex].align.split('|')
          if (bodyAlign) styles.textAlign = bodyAlign.trim()
        }

        // 处理单元格内容
        const content = typeof cell === 'object' ? cell : { text: cell }
        const td = createTableCell(content, cell, styles)
        if (td.colSpan > 1) jumpCols = td.colSpan - 1
        tr.appendChild(td)
      }

      // 边框处理[首列，末列]
      tr.children[0].style.borderLeft = '0'
      tr.children[tr.children.length - 1].style.borderRight = '0'

      // 处理首行和末行边框
      const borderStyle =
        rowIndex === 0 ? 'borderTop' : rowIndex === list.length - 1 ? 'borderBottom' : null
      if (borderStyle) {
        tr.querySelectorAll('td').forEach((td) => {
          td.style[borderStyle] = 'none'
        })
      }

      tbody.appendChild(tr)
    })

    table.appendChild(tbody)
  }

  return table
}

/**
 * 生成意见表格节点
 * @param {Object} node - 表格配置对象
 * @param {Array} node.data - 表格行数据数组
 * @param {string} [node.border='none'] - 边框显示模式('none'表示无边框)
 * @returns {HTMLTableElement} 生成的表格DOM元素
 *
 * @description
 * 该函数根据配置数据动态生成双行式意见表格：
 * 1. 每行数据渲染为两行表格行(tr)
 * 2. 第一行包含标签单元格(td1)和值单元格(td2)
 * 3. 第二行包含签名和时间信息的合并单元格(td3)
 * 4. 支持通过row对象自定义各元素的样式
 * 5. 自动处理首尾行的边框显示逻辑
 */
function generateOpinionTable(node) {
  const list = node.data || []
  const hasBorder = node.border || 'none'
  const layout = node.layout || 'table'

  const _obj2CssStr = (obj) => {
    return Object.entries(obj)
      .map(([key, value]) => `${key}:${value}`)
      .join(';')
  }

  let table = null

  // 内部table布局
  if (layout == 'table') {
    table = createStyledElement(
      'table',
      {
        width: '100%',
        ...STYLES.BASE_TABLE
      },
      'nested-table'
    )

    addStyleToDocument(STYLES.NESTED_TABLE, 'nested-table')

    if (list.length > 0) {
      const tbody = document.createElement('tbody')

      list.forEach((row, rowIndex) => {
        const tr = document.createElement('tr')

        const td1 = document.createElement('td')
        if (hasBorder === 'none') {
          applyCommonStyles(td1, { verticalAlign: 'top', ...row.labelStyle, borderRight: 'none' })
        } else {
          applyCommonStyles(td1, { verticalAlign: 'top', ...row.labelStyle })
        }

        td1.rowSpan = '2'
        td1.textContent = row.label
        if (row.labelHtml) {
          td1.innerHTML = row.labelHtml
        }

        const td2 = document.createElement('td')
        if (hasBorder === 'none') {
          applyCommonStyles(td2, { borderLeft: 'none', borderBottom: 'none' })
        } else {
          applyCommonStyles(td2, {})
        }
        td2.innerHTML = `
        <div style='${_obj2CssStr({ 'min-height': '52px', ...row.valueStyle })}'>
        ${row.value}
        </div>
        `

        tr.appendChild(td1)
        tr.appendChild(td2)

        const tr2 = document.createElement('tr')
        const td3 = document.createElement('td')
        if (hasBorder === 'none') {
          applyCommonStyles(td3, { borderLeft: 'none', borderTop: 'none' })
        } else {
          applyCommonStyles(td3, {})
        }

        td3.innerHTML = `
        <div style='line-height:1;width:400px;margin-left:auto;display:flex;justify-content:space-between;align-items:flex-end;'>
          <span style='${_obj2CssStr({ flex: 2, display: 'flex', 'align-items': 'flex-end', ...row.signParentStyle })}'>
            <span style='${_obj2CssStr({ 'white-space': 'nowrap', ...row.signLabelStyle })}'>${row.signLabel ? row.signLabel : '签字：'}</span>
            <span style='${_obj2CssStr({ ...row.signStyle })}'>
              ${row.signMode == 'img' && row.sign ? `<img title="${row.signTitle}" src="${row.sign}" style='width:100%;height:100%;'/>` : row.sign}
            </span>
          </span>
          <span style='${_obj2CssStr({ flex: 3, ...row.timeParentStyle })}'>
            <span style='${_obj2CssStr({ ...row.timeLabelStyle })}'>${row.timeLabel ? row.timeLabel : ''}</span>
            <span style='${_obj2CssStr({ ...row.timeStyle })}'>${row.time}</span>
          </span>
        </div>
        `
        tr2.appendChild(td3)

        // 处理首行和末行边框
        const borderStyle =
          rowIndex === 0 ? 'borderTop' : rowIndex === list.length - 1 ? 'borderBottom' : null
        if (borderStyle) {
          tr.querySelectorAll('td').forEach((td) => {
            td.style[borderStyle] = 'none'
          })
        }

        tbody.appendChild(tr)
        tbody.appendChild(tr2)
      })

      table.appendChild(tbody)
    }
  }
  // 内部div布局
  else {
    table = createStyledElement('div', {
      width: '100%'
    })
    if (list.length > 0) {
      list.forEach((row, rowIndex) => {
        const div = document.createElement('div')
        div.style.width = '100%'
        div.style.display = 'flex'
        div.style.flexDirection = 'row'
        div.style.borderBottom = '1px solid #ddd'

        if (rowIndex == list.length - 1) {
          div.style.borderBottom = 'none'
        }

        const divl = document.createElement('div')
        divl.textContent = row.label
        if (row.labelHtml) {
          divl.innerHTML = row.labelHtml
        }
        Object.assign(divl.style, row.labelStyle, { padding: '4px' })

        const divr = document.createElement('div')
        divr.style.flex = '1'
        divr.style.display = 'flex'
        divr.style.flexDirection = 'column'

        const divrt = document.createElement('div')
        divrt.style.flex = '1'
        divrt.style.minHeight = '60px'
        divrt.textContent = row.value
        if (row.valueHtml) {
          divrt.innerHTML = row.valueHtml
        }
        Object.assign(divrt.style, row.valueStyle, { padding: '4px' })

        const divrb = document.createElement('div')
        Object.assign(divrb.style, {
          padding: '4px',
          display: 'flex',
          justifyContent: 'flex-end',
          lineHeight: '1',
          alignItems: 'flex-end'
        })

        const divrbspan1 = document.createElement('span')
        Object.assign(divrbspan1.style, row.signParentStyle, {})
        const divrbspan1l = document.createElement('span')
        divrbspan1l.textContent = row.signLabel || '签字：'
        if (row.signLabelHtml) {
          divrbspan1l.innerHTML = row.signLabelHtml
        }
        Object.assign(divrbspan1l.style, row.signLabelStyle)
        const divrbspan1r = document.createElement('span')
        divrbspan1r.textContent = row.sign
        if (row.signHtml) {
          divrbspan1r.innerHTML = row.signHtml
        }
        if (row.signMode == 'img' && row.sign) {
          divrbspan1r.innerHTML = `<img title="${row.signTitle}" src="${row.sign}" style='width:100%;height:100%;'/>`
        }
        divrbspan1r.style.display = 'inline-block'
        divrbspan1r.style.width = '6em'

        Object.assign(divrbspan1r.style, row.signStyle)
        divrbspan1.appendChild(divrbspan1l)
        divrbspan1.appendChild(divrbspan1r)

        const divrbspan2 = document.createElement('span')
        Object.assign(divrbspan2.style, row.timeParentStyle, {})
        const divrbspan2l = document.createElement('span')
        divrbspan2l.textContent = row.timeLabel
        if (row.timeLabelHtml) {
          divrbspan2l.innerHTML = row.timeLabelHtml
        }
        Object.assign(divrbspan2l.style, row.timeLabelStyle)
        const divrbspan2r = document.createElement('span')
        divrbspan2r.textContent = row.time
        if (row.timeHtml) {
          divrbspan2r.innerHTML = row.timeHtml
        }
        divrbspan2r.style.display = 'inline-block'
        divrbspan2r.style.width = '12em'
        Object.assign(divrbspan2r.style, row.timeStyle)
        divrbspan2.appendChild(divrbspan2l)
        divrbspan2.appendChild(divrbspan2r)

        divrb.appendChild(divrbspan1)
        divrb.appendChild(divrbspan2)

        divr.appendChild(divrt)
        divr.appendChild(divrb)

        div.appendChild(divl)
        div.appendChild(divr)
        table.appendChild(div)
      })
    }
  }

  return table
}

/**
 * 生成完整表格结构
 * @param {Object} node - 表格配置对象
 * @param {string|Object} [node.title] - 表格标题，可以是文本或对象
 * @param {number} [node.columnsNum=1] - 表格列数
 * @param {Array} node.data - 表格数据数组
 * @param {Array} [node.header] - 表头配置数组
 * @param {Array} [node.footer] - 表尾配置数组
 * @param {string} [node.pageMode='A4-portrait'] - 页面模式(A3/A4, portrait/landscape)
 * @returns {HTMLDivElement} 包含完整表格结构的DIV容器
 * @description
 * 根据配置生成完整的表格结构，支持以下功能：
 * 1. 多种页面模式(A3/A4, portrait/landscape)
 * 2. 复杂表头/表尾配置
 * 3. 嵌套表格(NewTable模式)
 * 4. 列表表格(NewList模式)
 * 5. 响应式布局
 */
export function generateTable(node) {
  const { title, columnsNum, data = [], header, footer, pageMode = 'A4-portrait' } = node

  // ==================== 1. 初始化容器 ====================
  const container = document.createElement('div')
  Object.assign(container.style, {
    display: 'flex',
    flexDirection: 'column',
    margin: '0 auto'
  })

  // 设置容器宽度
  const [size, orientation] = (pageMode || '').split('-')
  switch (size) {
    case 'A4':
      container.style.width = orientation === 'portrait' ? '210mm' : '297mm'
      break
    case 'A3':
      container.style.width = orientation === 'portrait' ? '297mm' : '420mm'
      break
    default:
      container.style.width = '100%'
  }

  // ==================== 2. 生成表格标题 ====================
  if (title) {
    const titleDiv = document.createElement('div')
    if (typeof title === 'object') {
      if (title.textHtml) {
        titleDiv.innerHTML = title.textHtml
      } else {
        titleDiv.textContent = title.text || ''
      }
      if (title.style) Object.assign(titleDiv.style, title.style)
    } else {
      titleDiv.textContent = title
    }
    Object.assign(titleDiv.style, {
      fontWeight: 'bold',
      padding: '8px',
      width: '100%',
      textAlign: 'center'
    })
    container.appendChild(titleDiv)
  }

  // ==================== 3. 处理页眉/页脚 ====================
  // 处理页眉
  if (header?.length) {
    const headerDiv = document.createElement('div')
    Object.assign(headerDiv.style, {
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'center',
      padding: '8px',
      width: '100%'
    })

    header.forEach((cell) => {
      const item = document.createElement('div')
      Object.assign(item.style, {
        display: 'flex',
        gap: '8px',
        padding: '4px 8px',
        ...cell.parentStyle
      })

      const label = document.createElement('span')
      if (cell.labelHtml) {
        label.innerHTML = cell.labelHtml
      } else {
        label.textContent = cell.label || ''
      }
      if (cell.labelStyle) Object.assign(label.style, cell.labelStyle)

      const value = document.createElement('span')
      if (cell.valueHtml) {
        value.innerHTML = cell.valueHtml
      } else {
        value.textContent = cell.value || ''
      }
      if (cell.valueStyle) Object.assign(value.style, cell.valueStyle)

      item.appendChild(label)
      item.appendChild(value)
      headerDiv.appendChild(item)
    })

    container.appendChild(headerDiv)
  }

  // 处理页脚
  let footerDiv = null
  if (footer?.length) {
    footerDiv = document.createElement('div')
    Object.assign(footerDiv.style, {
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'center',
      padding: '8px',
      width: '100%'
    })

    footer.forEach((cell) => {
      const item = document.createElement('div')
      Object.assign(item.style, {
        display: 'flex',
        gap: '8px',
        padding: '4px 8px'
      })

      const label = document.createElement('span')
      if (cell.labelHtml) {
        label.innerHTML = cell.labelHtml
      } else {
        label.textContent = cell.label || ''
      }
      if (cell.labelStyle) Object.assign(label.style, cell.labelStyle)

      const value = document.createElement('span')
      if (cell.valueHtml) {
        value.innerHTML = cell.valueHtml
      } else {
        value.textContent = cell.value || ''
      }
      if (cell.valueStyle) Object.assign(value.style, cell.valueStyle)

      item.appendChild(label)
      item.appendChild(value)
      footerDiv.appendChild(item)
    })

    // container.appendChild(footerDiv);
  }

  // 创建中间容器
  const tableContainer = document.createElement('div')
  tableContainer.style.flexGrow = '1'
  tableContainer.style.overflow = 'hidden'

  // 创建基础表格
  const createBaseTable = () => {
    const table = document.createElement('table')
    Object.assign(table.style, STYLES.BASE_TABLE, {
      tableLayout: 'fixed',
      width: '100%'
    })

    // 使用顶部定义的getWidthWithUnit函数

    // 添加colgroup定义列宽(为每个label/value创建独立的col元素)
    const colgroup = document.createElement('colgroup')
    if (data.length > 0 && data[0].length > 0) {
      const firstRow = data[0]
      let colIndex = 0

      firstRow.forEach((cellData) => {
        if (!cellData) return

        // 处理label部分的列宽
        if ('label' in cellData) {
          const colspan = cellData.labelConfig?.colspan || 1
          for (let i = 0; i < colspan; i++) {
            const colElement = document.createElement('col')

            if (cellData.labelStyle?.width) {
              let widthWithUnit
              if (Array.isArray(cellData.labelStyle.width)) {
                widthWithUnit = cellData.labelStyle.width[i] || ''
              } else {
                widthWithUnit = cellData.labelStyle.width
              }

              widthWithUnit = getWidthWithUnit(widthWithUnit)
              if (widthWithUnit) {
                colElement.style.width = widthWithUnit
              }
            }
            colgroup.appendChild(colElement)
            colIndex++
          }
        }

        // 处理value部分的列宽
        if ('value' in cellData) {
          const colspan = cellData.valueConfig?.colspan || 1
          for (let i = 0; i < colspan; i++) {
            const colElement = document.createElement('col')

            if (cellData.valueStyle?.width) {
              let widthWithUnit
              if (Array.isArray(cellData.valueStyle.width)) {
                widthWithUnit = cellData.valueStyle.width[i] || ''
              } else {
                widthWithUnit = cellData.valueStyle.width
              }

              widthWithUnit = getWidthWithUnit(widthWithUnit)
              if (widthWithUnit) {
                colElement.style.width = widthWithUnit
              }
            }
            colgroup.appendChild(colElement)
            colIndex++
          }
        }
      })

      // 确保总列数与columnsNum一致
      while (colIndex < columnsNum) {
        colgroup.appendChild(document.createElement('col'))
        colIndex++
      }
    }
    table.appendChild(colgroup)

    if (pageMode) {
      const [size] = pageMode.split('-')
      if (size === 'A3' || size === 'A4') {
        table.style.minWidth = '100%'
      }
    }
    return table
  }

  const table = createBaseTable()

  // ==================== 6. 特殊模式处理 ====================
  /**
   * 处理NewTable模式(嵌套表格)
   * @param {Object} cellData - 单元格数据
   * @param {number} columnsNum - 总列数
   * @returns {HTMLTableCellElement} 处理后的单元格元素
   */
  function handleNewTableMode(cellData, columnsNum) {
    const cell = document.createElement('td')
    cell.colSpan = columnsNum
    Object.assign(cell.style, {
      padding: '0 !important',
      border: STYLES.BORDER
    })

    // 验证数据
    if (!cellData.data || !Array.isArray(cellData.data)) {
      console.error('Invalid nested table data:', cellData)
      return cell
    }

    // 创建嵌套表格
    const nestedTable = generateTable({
      title: cellData.title || '',
      columnsNum: cellData.columnsNum || columnsNum,
      data: cellData.data,
      header: cellData.header || [],
      footer: cellData.footer || [],
      pageMode: node.pageMode
    })

    // 设置嵌套表格样式
    Object.assign(nestedTable.style, {
      border: 'none',
      borderCollapse: 'collapse',
      tableLayout: 'auto',
      margin: '0',
      padding: '0'
    })
    nestedTable.classList.add('nested-table')
    addStyleToDocument(STYLES.NESTED_TABLE, 'nested-table')

    // 创建容器并添加表格
    const container = document.createElement('div')
    Object.assign(container.style, {
      padding: '0 !important',
      margin: '0 !important',
      border: 'none',
      overflow: 'hidden'
    })
    container.appendChild(nestedTable)
    cell.appendChild(container)

    return cell
  }

  /**
   * 处理NewList模式(列表表格)
   * @param {Object} cellData - 单元格数据
   * @param {number} columnsNum - 总列数
   * @returns {HTMLTableCellElement} 处理后的单元格元素
   */
  function handleNewListMode(cellData, columnsNum) {
    const cell = document.createElement('td')
    cell.colSpan = columnsNum
    Object.assign(cell.style, {
      padding: '0 !important',
      border: '1px solid #ddd'
    })

    // 验证数据
    if (!cellData.data || !cellData.data.columns || !cellData.data.list) {
      console.error('Invalid list table data:', cellData)
      return cell
    }

    // 创建列表表格
    const listTable = generateListTable({
      ...cellData,
      pageMode: node.pageMode
    })

    // 设置列表表格样式
    Object.assign(listTable.style, {
      border: 'none',
      borderCollapse: 'collapse',
      tableLayout: 'auto',
      margin: '0 !important',
      padding: '0 !important'
    })
    listTable.classList.add('list-table')
    addStyleToDocument(STYLES.LIST_TABLE, 'list-table')

    // 创建容器并添加表格
    const container = document.createElement('div')
    Object.assign(container.style, {
      padding: '0',
      margin: '0',
      border: 'none',
      overflow: 'hidden'
    })
    container.appendChild(listTable)
    cell.appendChild(container)

    return cell
  }

  /**
   * 处理意见模式的单元格渲染
   * @param {Object} cellData - 单元格数据对象，需包含data属性
   * @param {number} columnsNum - 单元格需要跨越的列数
   * @returns {HTMLTableCellElement} 返回处理后的td元素
   * @description 根据传入的单元格数据和列数，生成包含意见表格的td元素。若数据无效会返回空单元格并打印错误。
   */
  function handleOpinionMode(cellData, columnsNum) {
    const cell = document.createElement('td')
    cell.colSpan = columnsNum
    Object.assign(cell.style, {
      padding: '0 !important',
      border: '1px solid #ddd'
    })

    // 验证数据
    if (!cellData.data) {
      console.error('Invalid list table data:', cellData)
      return cell
    }

    const listTable = generateOpinionTable({
      ...cellData,
      pageMode: node.pageMode
    })

    // 创建容器并添加表格
    const container = document.createElement('div')
    Object.assign(container.style, {
      padding: '0',
      margin: '0',
      border: 'none',
      overflow: 'hidden'
    })
    container.appendChild(listTable)
    cell.appendChild(container)

    return cell
  }

  // ==================== 5. 处理表格主体内容 ====================
  const tbody = document.createElement('tbody')

  data.forEach((rowData) => {
    // 计算总列跨度
    let totalColspan = 0
    rowData.forEach((cellData) => {
      if (cellData.label && cellData.labelConfig?.colspan) {
        totalColspan += cellData.labelConfig.colspan
      } else if (cellData.label) {
        totalColspan += 1
      }

      if (cellData.value && cellData.valueConfig?.colspan) {
        totalColspan += cellData.valueConfig.colspan
      } else if (cellData.value) {
        totalColspan += 1
      }
    })

    // 跳过列跨度超过总列数的行
    if (totalColspan > columnsNum) {
      return
    }

    const row = document.createElement('tr')

    rowData.forEach((cellData) => {
      // 处理特殊模式(NewTable/NewList/Opinion)
      if (cellData.mode === 'NewTable') {
        row.appendChild(handleNewTableMode(cellData, node.columnsNum))
        return
      }
      // 新List
      if (cellData.mode === 'NewList') {
        row.appendChild(handleNewListMode(cellData, node.columnsNum))
        return
      }
      // 意见框
      if (cellData.mode === 'Opinion') {
        row.appendChild(handleOpinionMode(cellData, node.columnsNum))
        return
      }

      // 处理普通单元格
      if ('label' in cellData) {
        row.appendChild(createNormalCell(cellData, 'label'))
      }
      if ('value' in cellData) {
        row.appendChild(createNormalCell(cellData, 'value'))
      }
    })

    tbody.appendChild(row)
  })

  /**
   * 创建普通单元格
   * @param {Object} cellData - 单元格数据
   * @param {string} type - 单元格类型('label'或'value')
   * @returns {HTMLTableCellElement} 创建的单元格元素
   */
  function createNormalCell(cellData, type) {
    const content = cellData[type] || ''
    const cell = document.createElement('td')

    Object.assign(cell.style, {
      textAlign: type === 'label' ? 'center' : 'left',
      ...cellData[`${type}ParentStyle`]
    })

    // 处理特殊模式(img/link)
    const mode = cellData[`${type}Mode`]
    if (mode) {
      cell.innerHTML = ''
      if (mode === 'img' && cellData[`${type}ModeUrl`]) {
        const img = document.createElement('img')
        img.src = cellData[`${type}ModeUrl`]
        img.alt = content
        if (cellData[`${type}ModeStyle`]) {
          Object.assign(img.style, cellData[`${type}ModeStyle`])
        }
        cell.appendChild(img)
      } else if (mode === 'link' && cellData[`${type}ModeUrl`]) {
        const a = document.createElement('a')
        a.href = cellData[`${type}ModeUrl`]
        a.target = '_blank'
        a.textContent = content
        Object.assign(a.style, {
          color: 'blue',
          textDecoration: 'underline'
        })
        if (cellData[`${type}ModeStyle`]) {
          Object.assign(a.style, cellData[`${type}ModeStyle`])
        }
        cell.appendChild(a)
      } else if ((mode === 'radio' || mode === 'checkbox') && cellData[`${type}ModeOptions`]) {
        const _ary = document.createDocumentFragment()

        const raidoName =
          cellData[`${type}ModeRadioName`] ||
          cellData[`${type}ModeCheckboxName`] ||
          `radio_${randomNumber()}`

        cellData[`${type}ModeOptions`].forEach(({ label, value, labelStyle, valueStyle }) => {
          const radio = document.createElement('input')
          radio.type = mode || 'radio'
          radio.value = value
          radio.name = raidoName
          radio.id = `rdo_${randomNumber()}`
          Object.assign(
            radio.style,
            cellData[`${type}ModeStyle`],
            { cursor: 'pointer', verticalAlign: 'middle' },
            valueStyle
          )
          if (
            mode == 'radio' &&
            cellData[`${type}ModeValue`] &&
            cellData[`${type}ModeValue`] == value
          ) {
            radio.setAttribute('checked', true)
          } else if (
            mode == 'checkbox' &&
            cellData[`${type}ModeValue`] &&
            cellData[`${type}ModeValue`].includes(value)
          ) {
            radio.setAttribute('checked', true)
          }

          const lbl = document.createElement('label')
          lbl.textContent = label
          lbl.setAttribute('for', radio.id)
          Object.assign(
            lbl.style,
            cellData[`${type}ModeStyle`],
            { cursor: 'pointer', verticalAlign: 'middle' },
            labelStyle
          )

          _ary.appendChild(radio)
          _ary.appendChild(lbl)
        })

        cell.appendChild(_ary)
      } else {
        cell.textContent = content
      }
    } else {
      cell.textContent = content
      if (cellData[`${type}Html`]) {
        cell.innerHTML = cellData[`${type}Html`]
      }
    }

    // 应用配置
    const config = cellData[`${type}Config`]
    if (config) {
      if (config.colspan > 1) cell.colSpan = config.colspan
      if (config.rowspan > 1) cell.rowSpan = config.rowspan
    }

    // 应用样式
    Object.assign(cell.style, {
      border: STYLES.BORDER,
      padding: STYLES.PADDING,
      ...(cellData[`${type}Style`] || {})
    })

    return cell
  }

  table.appendChild(tbody)
  tableContainer.appendChild(table)
  container.appendChild(tableContainer)
  footerDiv && container.appendChild(footerDiv)

  return container
}

/**
 * 生成多个表格的文档片段
 * @param {Array} list - 包含表格数据的数组
 * @returns {DocumentFragment} 包含所有生成表格的文档片段
 */
export function generateMultipleTable(list) {
  const result = document.createDocumentFragment()
  if (list && Array.isArray(list) && list.length) {
    list.forEach((node) => {
      const tab = generateTable(node)
      result.appendChild(tab)
    })
  }
  return result
}
